#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include <signal.h>
#include "wrap.h"

#define MAXLINE 80
#define SERV_PORT 8000

void sig_chld(int signo)
{
    printf("%s\n", __FUNCTION__);
    waitpid(getpid(), NULL, 0);
    return;
}

int main(void)
{
    struct sockaddr_in serv_addr, cli_addr;
    socklen_t cli_addr_len;
    int listen_fd, conn_fd;
    char buf[MAXLINE];
    char str[INET_ADDRSTRLEN];
    int i, n;
    
    struct sigaction new_act, old_act;
    pid_t pid;

    new_act.sa_handler = sig_chld;
    sigemptyset(&new_act.sa_mask);
    new_act.sa_flags = 0;
    sigaction(SIGCHLD, &new_act, &old_act);

    listen_fd = Socket(AF_INET, SOCK_STREAM, 0);

    bzero(&serv_addr, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    serv_addr.sin_port = htons(SERV_PORT);

    Bind(listen_fd, (struct sockaddr *)&serv_addr, \
            sizeof(serv_addr));
    Listen(listen_fd, 20);

    printf("Accepting connections ...\n");
    while (1) {
        cli_addr_len = sizeof(cli_addr);
        conn_fd = Accept(listen_fd, (struct sockaddr *)&cli_addr, \
                &cli_addr_len);
        pid = fork();
        if (pid == -1) {
            perror("call fork.");
            exit(1);
        } else if (pid == 0) {
            close(listen_fd);
            while (1) {
                n = Read(conn_fd, buf, MAXLINE);
                if (n == 0) {
                    printf("client closed.\n");
                    break;
                }
                printf("received from %s at PORT:%d\n", \
                   (char *)inet_ntop(AF_INET, &cli_addr.sin_addr, \
                        str, sizeof(str)), \
                    ntohs(cli_addr.sin_port));
                for (i = 0; i < n; i++)
                    buf[i] = toupper(buf[i]);
                Write(conn_fd, buf, n);
            }
            sigaction(SIGCHLD, &old_act, NULL);
            Close(conn_fd);
            exit(0);
        } else
            Close(conn_fd);
    }
}

